package com.winit.schedule.job.tracker.repository.mysql;

import java.util.Arrays;
import java.util.List;

import javax.annotation.Resource;

import com.winit.schedule.core.repository.entity.*;
import com.winit.schedule.job.tracker.repository.mysql.dao.MysqlUserLogDao;
import com.winit.schedule.job.tracker.util.RequestUtils;
import com.winit.schedule.job.tracker.web.auth.User;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import com.alibaba.fastjson.JSON;
import com.winit.schedule.core.model.AssignedTask;
import com.winit.schedule.core.model.JobID;
import com.winit.schedule.core.repository.constants.LogType;
import com.winit.schedule.core.utils.Clock;
import com.winit.schedule.job.tracker.repository.LogDataManager;
import com.winit.schedule.job.tracker.repository.mysql.dao.MysqlLogDao;
import com.winit.schedule.job.tracker.repository.mysql.dao.MysqlQuartzLogDao;

@Service("logDataManager")
@Transactional
public class MysqlLogDataManager implements LogDataManager {

    private static final Logger logger = LoggerFactory.getLogger(MysqlLogDataManager.class);

    @Resource
    protected MysqlLogDao       logDao;

    @Resource
    protected MysqlUserLogDao userLogDao;

    @Resource
    protected MysqlQuartzLogDao quartzLogDao;

    @Value("${uschedule.develop.mode:false}")
    private boolean develoyMode;

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void logger(JobEntity job, List<String> taskIds, boolean updateJob) {
            try {
                UserLogEntity log = new UserLogEntity();

                log.setJobId(job.getJobId().getJobId());
                log.setLogTime(Clock.getSystemTime());
                if (updateJob) {
                    log.setLogType(LogType.UPDATE_JOB);
                } else {
                    log.setLogType(LogType.CREATE_JOB);
                }

                User loginUser = RequestUtils.getLoginUser();
                if (null != loginUser) {
                    log.setOperator(loginUser.getUsername());
                }

                log.setUserAction(true);
                log.setContent("Job:" + JSON.toJSONString(job) + ", Task:" + JSON.toJSONString(taskIds));
                userLogDao.saveLog(log);
            } catch (Exception e) {
                logger.error("Logger save failure." + e);
            }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void logger(JobID jobId, LogType logType) {

            try {
                UserLogEntity log = new UserLogEntity();
                log.setJobId(jobId.getJobId());
                log.setLogTime(Clock.getSystemTime());
                log.setLogType(logType);
                log.setUserAction(true);
                log.setContent("JobId:" + JSON.toJSONString(jobId));

                User loginUser = RequestUtils.getLoginUser();
                if (null != loginUser) {
                    log.setOperator(loginUser.getUsername());
                }
                userLogDao.saveLog(log);
            } catch (Exception e) {
                logger.error("Logger save failure." + e);
            }

    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void logger(List<AssignedTask> tasks, String exception, String taskTrackerUuid, LogType logType) {
            try {

                if (!StringUtils.isEmpty(exception) && exception.length() > 4000) {
                    exception = exception.substring(0, 3999);
                }

                if (null != tasks) {
                    LogEntity log = null;
                    long currentTime = Clock.getSystemTime();
                    for (AssignedTask task : tasks) {
                        log = new LogEntity();
                        log.setLogTime(currentTime);
                        log.setJobId(task.getTaskId().getJobId().getJobId());
                        log.setTaskId(task.getTaskId().getTaskId());
                        log.setLogType(logType);
                        log.setUserAction(false);
                        log.setTaskTrackerUuid(taskTrackerUuid);
                        log.setContent(exception);
                        logDao.saveLog(log);
                    }
                }
            } catch (Exception e) {
                logger.error("Logger save failure." + e);
            }

    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public void logger(List<AssignedTask> tasks, String taskTrackerUuid, LogType logType) {
            try {
                if (null != tasks) {
                    StringBuilder builder = null;
                    for (AssignedTask task : tasks) {
                        builder = new StringBuilder();
                        builder.append("UUID:").append(taskTrackerUuid)
                                .append(", id:").append(task.getTaskId().getId())
                                .append(", type:").append(logType);

                        if(null != task.getTaskItems() && task.getTaskItems().size() > 0) {
                            builder.append(", status:").append(task.getTaskItems().get(0).getTaskItemStatus())
                                    .append(", statusUpdateTime:").append(task.getTaskItems().get(0).getLastStatusUpdateTime());
                        }
                        logger.info(builder.toString());
                    }
                }
            } catch (Exception e) {
                logger.error("Logger save failure." + e);
            }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void logger(String taskTrackerUuid, LogType logType) {
            try {
                LogEntity log = new LogEntity();
                log.setLogTime(Clock.getSystemTime());
                log.setLogType(logType);
                log.setUserAction(false);
                log.setTaskTrackerUuid(taskTrackerUuid);
                logDao.saveLog(log);
            } catch (Exception e) {
                logger.error("Logger save failure." + e);
            }

    }

    @Override
    @Transactional(propagation = Propagation.SUPPORTS, readOnly = true)
    public void logger(QuartzLogEntity entity) {
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void logger(TaskEntity task, LogType logType) {
        try {
            UserLogEntity log = new UserLogEntity();
            log.setLogTime(Clock.getSystemTime());
            log.setLogType(logType);
            log.setUserAction(true);
            log.setTaskId(task.getTaskId().getTaskId());
            if (null != task.getTaskId().getJobId()) {
                log.setJobId(task.getTaskId().getJobId().getJobId());
            }
            log.setContent(JSON.toJSONString(task));

            User loginUser = RequestUtils.getLoginUser();
            if (null != loginUser) {
                log.setOperator(loginUser.getUsername());
            }
            userLogDao.saveLog(log);
        } catch (Exception e) {
            logger.error("Logger save failure." + e);
        }
    }

    @Override
    @Transactional(propagation = Propagation.REQUIRED)
    public void logger(String[] items, LogType logType) {
        try {
            if (null != items && items.length > 0) {
                UserLogEntity log = new UserLogEntity();
                log.setLogTime(Clock.getSystemTime());
                log.setLogType(logType);
                log.setUserAction(true);
                User loginUser = RequestUtils.getLoginUser();
                if (null != loginUser) {
                    log.setOperator(loginUser.getUsername());
                }
                for (int i = 0 ; i < items.length ; i++) {
                    log.setTaskId(items[i]);
                    userLogDao.saveLog(log);
                }
            }
        } catch (Exception e) {
            logger.error("Logger save failure." + e);
        }
    }

    @Override public void logger(UserEntity user, LogType logType) {
        try {
            if (null != user) {

                UserLogEntity log = new UserLogEntity();
                log.setLogTime(Clock.getSystemTime());
                log.setLogType(logType);
                log.setUserAction(true);
                log.setContent(JSON.toJSONString(user));
                log.setOperator(user.getUsername());

                userLogDao.saveLog(log);
            }
        } catch (Exception e) {
            logger.error("Logger save failure." + e);
        }
    }

}
